from abc import abstractmethod
from enum import Enum
from typing import List
from typing import NamedTuple
from trashcli.compat import Protocol


class Level(Enum):
    INFO = "INFO"
    DEBUG = "DEBUG"
    WARNING = "WARNING"


class LogTag(Enum):
    "tags used only during testing"

    unspecified = "unspecified"
    trash_failed = "trash_failed"


class LogData:
    def __init__(self, program_name, verbose):
        self.program_name = program_name
        self.verbose = verbose


class Message(Protocol):
    @abstractmethod
    def resolve(self):
        raise NotImplementedError


class LogEntry(
    NamedTuple(
        "LogEntry",
        [
            ("level", Level),
            ("tag", LogTag),
            ("messages", List[Message]),
        ],
    )
):
    def resolve_messages(self):
        for m in self.messages:
            yield m.resolve()


class MessageStr(
    NamedTuple(
        "Message",
        [
            ("message", str),
        ],
    ),
    Message,
):
    def resolve(self):
        return self.message

    @staticmethod
    def from_messages(
        messages,  # type: List[str]
    ):
        return [MessageStr(msg) for msg in messages]


def log_str(
    level,  # type: Level
    tag,  # type: LogTag
    messages,  # type: List[str]
):
    return LogEntry(level, tag, MessageStr.from_messages(messages))


def warning_str(message):  # type: (str) -> LogEntry
    return log_str(Level.WARNING, LogTag.unspecified, [message])


def info_str(message):  # type: (str) -> LogEntry
    return log_str(Level.INFO, LogTag.unspecified, [message])


def debug_str(message):  # type: (str) -> LogEntry
    return log_str(Level.DEBUG, LogTag.unspecified, [message])
